/**
 **oj/os - Operating system interface
 *
 * The os module interfaces with the oj file service to provide file system operations.
 *
 */

define(['oj/remote'], function(remote) {
    
    window['os'] = {}
    
    
    os['environ'] = {
        cwd: '/'
    }
    
    
    os['system'] = function(path, commands, callback) {
        /**
         *> os.system('path', [commands], callback)
         * 
         * Execute a list of server commands.
         * 
         */
        
        remote.jsonp(path, 'P/', commands.join('&'), callback)
    }
    
    
    os['identity'] = function(destUrl, callback) {
        /**
         *> os.identity('destUrl', callback)
         * 
         * Get user identity.
         * 
         */
        
        os.system('/', ['I/' + destUrl], callback)
    }
    
    
    os['logout'] = function(destUrl, callback) {
        /**
         *> os.logout('destUrl', callback)
         * 
         * Logs user out.
         * 
         */
        
        os.system('/', ['E/' + destUrl], callback)
    }
    
    
    os['read'] = function(path, callback) {
        /**
         *> os.read('path', callback)
         * 
         * Reads a path from the server.
         * 
         */
        os.system(path, ['R/'], callback)
    }
    
    
    os['write'] = function(path, content, callback) {
        /**
         *> os.write('path', 'content', callback)
         * 
         * Write content to path.
         * 
         */
        
        os.system(path, ['W/' + content], callback)
    }
    
    
    os['chdir'] = function(path, callback) {
        /**
         *> os.chdir('path', callback)
         * 
         * Changes the current working directory.
         * 
         */
        
        path = os.path.abspath(path + '/')
        os.read(path, function(read) {
            if (!oj.isError(read))
                os.environ.cwd = path
            
            if (typeof callback === 'function')
               callback(read)
            
        })
    }
    
    
    os['mkdir'] = function(path, callback) {
        /**
         *> os.mkdir('path', callback)
         * 
         * Creates a new directory.
         * 
         */
        
        os.system(os.path.abspath(path + '/'), ['M/'], callback)
    }
    
    
    os['rmdir'] = function(path, callback) {
        /**
         *> os.rmdir('path', callback)
         * 
         * Removes a directory.
         * 
         */
        os.system(os.path.abspath(path + '/'), ['X/'], callback)
    }
    
    
    os['listdir'] = function(path, callback) {
        /**
         *> os.listdir('path', callback)
         * 
         * Returns a list of files and directories.
         * 
         */
        
        if (typeof path === 'undefined' || path === '')
            path = '.'
        
        
        os.read(os.path.abspath(path + '/'), function (m) {
            try {
                m = JSON.parse(m)
            } catch (err) {}
            if (typeof callback === 'function') {
                callback(m)
            }
        })
    }
    
    
    os['move'] = function(src, dst, callback) {
        /**
         *> os.move('src', 'dst', callback)
         * 
         * Moves a file or directory from src to dst.
         * 
         */
        os.system(os.path.abspath(src), ['N/' + os.path.abspath(dst)], callback)
    }
    
    
    os['remove'] = function(path, callback) {
        /**
         *> os.remove('path', callback)
         * 
         * Removes file at path.
         * 
         */
        
        os.system(os.path.abspath(path), ['D/'], callback)
    }
    
    
    os['concat'] = function(paths, clean, callback) {
        /**
         *> os.concat([paths], clean, callback)
         * 
         * Concatenates a list of files to one file.
         *
         *. os.concat( args, false, function (msg) {
         *.     var error = oj.isError(msg);
         *. });
         *
         */
        
        var path = os.path.abspath(paths.pop()),
            cmd = (clean) ? 'CR/' : 'C/',
            i = paths.length
        
        while (--i)
            paths[i] = os.path.abspath(paths[i])
        
        
        os.system(path, [cmd + paths.join('!')], callback)
    }
    
    
    os['path'] = {}
    
    os.path['abspath'] = function(path) {
        /**
         *> os.path.abspath('path')
         * 
         * Returns a normalised absolute path.
         * 
         */
        var p = (/^\//.test(path) ? path : os.environ.cwd + path).split('/'),
            abs = [],
            i = -1,
            result
    
        while (++i < p.length) {
            if (p[i].length !== 0) {
                if (/^\.\.$/.test(p[i]))
                    abs.pop()
                else if (!/^\.$/.test(p[i]))
                    abs.push(p[i])
            }
        }
        
        result = '/' + abs.join('/')
        
        if (path.lastIndexOf('/') === path.length - 1 && abs.length > 0)
            result += '/'
        
        
        return result
    }
    
    
    os.path['isdir'] = function(path, callback) {
        /**
         *> os.path.isdir('path', callback)
         * 
         * Calls callback with true if path is an existing directory,
         * otherwise false.
         * 
         */
        
        os.read(os.path.abspath(path + '/'), function(m) {
            if (typeof callback === 'function')
                callback(!oj.isError(m))
        })
    }
	
    
    os.path['basename'] = function(path) {
        /**
         *> os.path.basename('path')
         * 
         * Return the base name of path.
         */
        
        if (/\/$/.test(path))
            return ''
            
        if (path === '')
            return null
        
        return path.split('/').pop()
    }
    
    
    os.path['dirname'] = function(path) {
        /**
         *> os.path.basename('path')
         * 
         * Return the base name of path.
         */
        
        if (/\/$/.test(path))
            return path
            
        if (path === '')
            return null
        
        path = path.split('/')
        path.pop()
        
        return path.join('/') + '/'
    }
    
    return os
    
})
